package org.ala.tiktools.rpc.netty.handler;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;

import org.ala.tiktools.rpc.netty.attr.RpcAttribute;
import org.ala.tiktools.tools.kv.Maps;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * channel生命周期监听器
 *
 * @author ala
 * @date 2025-04-09 13:24
 */
public class RpcChannellifecycleListener extends ChannelInboundHandlerAdapter {


    /**
     *  注册完成回调，注销完成回调
     */
    protected Consumer<Channel> registered, unRegistered;
    public RpcChannellifecycleListener(Consumer<Channel> registered, Consumer<Channel> unRegistered) {
        this.registered = registered;
        this.unRegistered = unRegistered;
    }

    /**
     * 当channel被注册给EventLoop后触发
     * <p>  此时channel已经可以正常接收轮训。但还不能收发消息
     * <p>  在channelActive被触发时，初始化工作才算完成，channel才能正常收发消息
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        //  初始化ackMapper
        ctx.channel().attr(RpcAttribute.ackMapper).set(new HashMap<>());

        if (registered != null) {
            registered.accept(ctx.channel());
        }
        super.channelRegistered(ctx);
    }

    /**
     * 当channel从EventLoop中摘掉后触发，此时channel已经无法接收轮训。不能收发消息
     */
    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        //  清掉channel上绑定的attr
        Map<Long, CompletableFuture<?>> map = ctx.channel().attr(RpcAttribute.ackMapper).getAndSet(null);
        if (!Maps.isEmpty(map)) {
            map.clear();
        }

        //  全部清除完毕后，执行回调
        if (unRegistered != null) {
            unRegistered.accept(ctx.channel());
        }
        super.channelUnregistered(ctx);
    }
}
